package com.dlc.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dlc.shop.allinpay.service.AllinpayCompanyService;
import com.dlc.shop.bean.app.param.ShopAuditingParam;
import com.dlc.shop.bean.dto.allinpay.AllinpayShopBankCardDTO;
import com.dlc.shop.bean.dto.allinpay.SetCompanyInfoDTO;
import com.dlc.shop.bean.enums.AuditStatus;
import com.dlc.shop.bean.enums.ShopStatus;
import com.dlc.shop.bean.event.ShopApplyEvent;
import com.dlc.shop.bean.model.*;
import com.dlc.shop.bean.vo.ShopCompanyVO;
import com.dlc.shop.common.allinpay.constant.AllinpayConstant;
import com.dlc.shop.common.allinpay.constant.AllinpayNoticeUrl;
import com.dlc.shop.common.allinpay.constant.AllinpayShopStatus;
import com.dlc.shop.common.allinpay.constant.CompanyInfoProcessStatus;
import com.dlc.shop.common.allinpay.member.resp.BindCard;
import com.dlc.shop.common.allinpay.member.resp.CompanyInfo;
import com.dlc.shop.common.allinpay.member.resp.SetCompanyInfoResp;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.enums.StatusEnum;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.util.BeanUtil;
import com.dlc.shop.config.ShopConfig;
import com.dlc.shop.dao.ShopBankCardMapper;
import com.dlc.shop.dao.ShopCompanyMapper;
import com.dlc.shop.dao.ShopDetailMapper;
import com.dlc.shop.service.CompanyAuditingService;
import com.dlc.shop.service.ShopAuditingService;
import com.dlc.shop.service.ShopBankCardService;
import com.dlc.shop.service.ShopDetailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 商家钱包信息
 *
 * @author YXF
 * * @date 2020-04-07 14:22:08
 */
@Service
public class ShopBankCardServiceImpl extends ServiceImpl<ShopBankCardMapper, ShopBankCard> implements ShopBankCardService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ShopBankCardServiceImpl.class);
    @Autowired
    private ShopBankCardMapper shopBankCardMapper;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private ShopDetailMapper shopDetailMapper;
    @Autowired
    private AllinpayCompanyService allinpayCompanyService;
    @Autowired
    private CompanyAuditingService companyAuditingService;
    @Autowired
    private ShopAuditingService shopAuditingService;
    @Autowired
    private ShopDetailService shopDetailService;
    @Autowired
    private ShopCompanyMapper shopCompanyMapper;
    @Autowired
    private ShopConfig shopConfig;
    private static final Integer NOT_DEFAULT = 0;
    private static final Integer DEFAULT = 1;

    @Override
    public Long insertSelective(ShopBankCard shopBankCard) {
        //银行卡卡号重复判断
        long cardCount = shopBankCardMapper.selectCount(new LambdaQueryWrapper<ShopBankCard>()
                .eq(ShopBankCard::getCardNo, shopBankCard.getCardNo())
                .eq(ShopBankCard::getShopId, shopBankCard.getShopId())
                .eq(ShopBankCard::getStatus, StatusEnum.ENABLE.value()));

        if (cardCount > 0) {
            throw new YamiShopBindException("yami.shop.card.is.exist");
        }
        long count = shopBankCardMapper.selectCount(new LambdaQueryWrapper<ShopBankCard>()
                .eq(ShopBankCard::getShopId, shopBankCard.getShopId())
                .eq(ShopBankCard::getStatus, 1)
        );
        if (count == 0) {
            shopBankCard.setIsDefault(DEFAULT);
        } else {
            shopBankCard.setIsDefault(NOT_DEFAULT);
        }
        shopBankCardMapper.insertSelective(shopBankCard);
        return shopBankCard.getShopBankCardId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertAndSetCompanyInfo(AllinpayShopBankCardDTO allinpayShopBankCardDTO, Long shopId, ShopCompany shopCompany) {
        // 保存数据到数据库
        shopBankCardMapper.delete(new LambdaQueryWrapper<ShopBankCard>().eq(ShopBankCard::getShopId, shopId));
        ShopBankCard shopBankCard = new ShopBankCard();
        shopBankCard.setShopId(shopId);
        shopBankCard.setBankName(allinpayShopBankCardDTO.getParentBankName());
        shopBankCard.setOpeningBank(allinpayShopBankCardDTO.getBankName());
        shopBankCard.setRecipientName(shopCompany.getFirmName());
        shopBankCard.setCardNo(allinpayShopBankCardDTO.getAccountNo());
        shopBankCard.setStatus(StatusEnum.ENABLE.value());
        shopBankCard.setUnionBank(allinpayShopBankCardDTO.getUnionBank());
        shopBankCard.setBankCardPro(1);
        shopBankCard.setBankCardNo(allinpayShopBankCardDTO.getAccountNo());
        shopBankCardMapper.insert(shopBankCard);
        ShopDetail shopDetail = shopDetailMapper.selectShopDetailById(shopId);
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.APPLYING.value())) {
            LOGGER.info("店铺{}提交开店申请", shopId + "shopName：" + shopDetail.getShopName());
            // 提交开店申请
            applicationContext.publishEvent(new ShopApplyEvent(shopId, null));
        }
        // 通联设置企业信息及后续处理
        allinpaySetCompanyInfo(allinpayShopBankCardDTO, shopId, shopCompany, shopDetail);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void allinpaySetCompanyInfo(AllinpayShopBankCardDTO allinpayShopBankCardDTO, Long shopId, ShopCompany shopCompany, ShopDetail shopDetailVO) {
        SetCompanyInfoDTO setCompanyInfoDTO = BeanUtil.map(allinpayShopBankCardDTO, SetCompanyInfoDTO.class);
        setCompanyInfoDTO.setCompanyName(shopCompany.getFirmName());
        setCompanyInfoDTO.setCompanyAddress(shopCompany.getResidence());
        setCompanyInfoDTO.setUniCredit(shopCompany.getCreditCode());
        setCompanyInfoDTO.setLegalName(shopCompany.getRepresentative());
        setCompanyInfoDTO.setLegalPhone(shopCompany.getLegalPhone());
        setCompanyInfoDTO.setLegalIds(shopCompany.getLegalIds());
        setCompanyInfoDTO.setBizUserId(AllinpayConstant.SHOP + shopId);
        // 设置完企业信息——店铺变为上线待审核(已开店)/开店待审核(未开店)——回调假如成功更改为营业，失败则为审核失败，重新填写，平台开店也一样
        String domainUrl = shopConfig.getDomain().getApiDomainName();
        String backUrl = domainUrl + AllinpayNoticeUrl.SET_COMPANY_INFO;
        SetCompanyInfoResp response = allinpayCompanyService.setCompanyInfo(Long.valueOf(setCompanyInfoDTO.getBizUserId().substring(AllinpayConstant.SHOP_LENGTH)),
                backUrl, setCompanyInfoDTO);
        LOGGER.info("店铺{}设置企业信息结果：{}", shopId + "shopName：" + shopDetailVO.getShopName(), response);
        CompanyAuditing companyAuditing = companyAuditingService.getLatestAuditingByShopId(shopId);
        String failReason = response.getFailReason();
        if (Objects.equals(response.getResult(), AuditStatus.FAIL.value())) {
            if (Objects.equals(failReason, AllinpayConstant.SET_COMPANY_INFO_RESULT)) {
                LOGGER.info("当前商家在通联已审核通过，无法设置企业信息。更新店铺状态，上传影印件，等待影印件通过审核。");
                // 审核成功 更新店铺企业信息审核状态为审核通过，待影印件通过后即可将通联店铺状态更改为营业中,并且把工商信息修改为成功
                updateShopStatusToWaitAudit(shopId, shopDetailVO, companyAuditing);
                companyAuditingService.updateAllinpayShopStatus(AllinpayConstant.SHOP + shopId, AuditStatus.SUCCESS.value(), "");
                return;
            }
            // 更新审核失败
            if (Objects.nonNull(companyAuditing)) {
                // 如果是已经开店来审核的话要把审核拒绝通过
                if (Objects.equals(companyAuditing.getStatus(), AuditStatus.FAILAUDIT.value())) {
                    LOGGER.info("已开店商家：{}审核失败，更新失败原因：{}", shopId + "shopName：" + shopDetailVO.getShopName(), failReason);
                    companyAuditingService.updateRemark(new CompanyAuditing(companyAuditing.getCompanyAuditingId(), AuditStatus.FAILAUDIT.value(), failReason));
                } else {
                    LOGGER.info("已开店商家：{}审核失败，开店拒绝通过，原因为：{}", shopId + "shopName：" + shopDetailVO.getShopName(), failReason);
                    companyAuditingService.audit(new CompanyAuditing(companyAuditing.getCompanyAuditingId(), AuditStatus.FAILAUDIT.value(), failReason));
                }
            }
            Boolean isPlatformApply = Objects.equals(shopDetailVO.getIsPlatform(), 1)
                    && !Objects.equals(shopDetailVO.getAllinpayShopStatus(), AllinpayShopStatus.OPEN.value())
                    && !ShopStatus.isOpen(shopDetailVO.getShopStatus());
            if (Objects.equals(shopDetailVO.getShopStatus(), ShopStatus.APPLYING.value()) || isPlatformApply) {
                // 申请拒绝
                ShopAuditing shopAuditing = shopAuditingService.getOne(new LambdaQueryWrapper<ShopAuditing>().eq(ShopAuditing::getShopId, shopId));
                Integer shopAuditingStatus = shopAuditing.getStatus();
                shopAuditing.setRemarks(failReason);
                if (Objects.equals(shopAuditingStatus, AuditStatus.FAILAUDIT.value())) {
                    shopAuditing.setStatus(AuditStatus.FAILAUDIT.value());
                    LOGGER.info("申请开店商家：{}审核失败，更新失败原因：{}", shopId + "shopName：" + shopDetailVO.getShopName(), failReason);
                    shopAuditingService.updateById(shopAuditing);
                } else {
                    LOGGER.info("申请开店商家：{}审核失败，开店拒绝通过，原因为：{}", shopId + "shopName：" + shopDetailVO.getShopName(), failReason);
                    ShopAuditingParam shopAuditingDTO = BeanUtil.map(shopAuditing, ShopAuditingParam.class);
                    shopAuditingDTO.setStatus(AuditStatus.FAILAUDIT.value());
                    shopAuditingDTO.setAuditorId(null);
                    shopDetailService.audit(shopAuditingDTO);
                }
            }
            shopDetailMapper.updateShopAuditFail(shopId);
            return;
        }
        updateShopStatusToWaitAudit(shopId, shopDetailVO, companyAuditing);
        if (Objects.nonNull(response.getResult())) {
            LOGGER.info("通联回调不为空，进行店铺审核后续处理");
            companyAuditingService.updateAllinpayShopStatus(response.getBizUserId(), response.getResult(), "");
        }
    }

    @Override
    public void updateShopAllinpayStatusToSuccess(Long shopId) {
        ShopDetail shopDetailVO = shopDetailMapper.selectShopDetailById(shopId);
        if (Objects.isNull(shopDetailVO)) {
            return;
        }
        if (Objects.equals(shopDetailVO.getCompanyInfoProcessStatus(), CompanyInfoProcessStatus.SUCCESS.value())) {
            return;
        }
        shopDetailMapper.updateShopAuditSuccess(shopId);
    }

    private void updateShopStatusToWaitAudit(Long shopId, ShopDetail shopDetailVO, CompanyAuditing companyAuditing) {
        if (Objects.nonNull(companyAuditing) && Objects.equals(companyAuditing.getStatus(), AuditStatus.WAITAUDIT.value())) {
            LOGGER.info("已开店商家：{}审核失败，更新店铺状态为上线待审核", shopId + "shopName：" + shopDetailVO.getShopName());
            // 已经开店来审核更改为上线待审核
            shopDetailMapper.updateAllinpayShopStatus(shopId, AllinpayShopStatus.WAIT_AUDIT.value());
        } else {
            LOGGER.info("申请开店商家：{}审核失败，更新店铺状态为开店待审核", shopId + "shopName：" + shopDetailVO.getShopName());
            // 未开店更改为开店待审核
            shopDetailMapper.updateAllinpayShopStatus(shopId, AllinpayShopStatus.OPEN_WAIT_AUDIT.value());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertBatchAndSubmitApply(List<ShopBankCard> shopBankCards, Long shopId, Long employeeId) {
        if (CollUtil.isEmpty(shopBankCards)) {
            throw new YamiShopBindException("yami.shop.bank.card.not.empty");
        }
        // 先删除已保存的银行卡信息
        shopBankCardMapper.delete(Wrappers.lambdaQuery(ShopBankCard.class).eq(ShopBankCard::getShopId, shopId));
        // 先检查银行卡信息
        this.checkSaveBankCardList(new ArrayList<>(), shopBankCards, shopId);
        // 保存银行卡信息]
        if(shopBankCards.size() == 1){
            shopBankCards.get(0).setShopId(shopId);
            this.insertSelective(shopBankCards.get(0));
        }else{
            shopBankCardMapper.insertBatch(shopBankCards, shopId);
        }

        // 提交开店申请
        applicationContext.publishEvent(new ShopApplyEvent(shopId, employeeId));
    }

    @Override
    public void saveBatchByShopId(List<ShopBankCard> shopBankCardList, Long shopId) {
        if (CollUtil.isEmpty(shopBankCardList)) {
            return;
        }
        List<ShopBankCard> shopBankCards = shopBankCardMapper.selectList(Wrappers.lambdaQuery(ShopBankCard.class).eq(ShopBankCard::getShopId, shopId));
        if (CollUtil.isEmpty(shopBankCards)) {
            shopBankCards = new ArrayList<>();
        }
        // 检查银行卡信息
        this.checkSaveBankCardList(shopBankCards, shopBankCardList, shopId);
        if(shopBankCards.size() == 1){
            shopBankCards.get(0).setShopId(shopId);
            this.insertSelective(shopBankCards.get(0));
        }else{
            shopBankCardMapper.insertBatch(shopBankCardList, shopId);
        }

    }

    @Override
    public void setNotDefault(Long shopBankCardId, Long shopId) {
        shopBankCardMapper.setNotDefault(shopBankCardId, shopId);
    }

    @Override
    public void updateByShopId(ShopBankCard shopBankCard, Long shopId) {
        if (Objects.isNull(shopBankCard.getShopBankCardId())) {
            throw new YamiShopBindException("银行卡id不能为空");
        }
        long count = shopBankCardMapper.selectCount(Wrappers.lambdaQuery(ShopBankCard.class)
                .eq(ShopBankCard::getShopId, shopId)
                .eq(ShopBankCard::getCardNo, shopBankCard.getCardNo())
                .eq(ShopBankCard::getStatus, 1)
                .ne(ShopBankCard::getShopBankCardId, shopBankCard.getShopBankCardId())
        );
        if (count > 0) {
            throw new YamiShopBindException("yami.shop.bank.card.no.repeat");
        }
        shopBankCardMapper.updateById(shopBankCard);
    }

    @Override
    public void setDefault(Long shopBankCardId, Long shopId) {
        shopBankCardMapper.setDefault(shopBankCardId, shopId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refresh(Long shopId) {
        List<BindCard> bindCards = allinpayCompanyService.queryBankCard(shopId, null);
        CompanyInfo companyInfo = allinpayCompanyService.getCompanyInfo(AllinpayConstant.SHOP + shopId);
        bindCards.forEach(card -> card.setAccountNo(companyInfo.getAccountNo()));
        List<BindCard> bindCardList = bindCards.stream().filter(card -> Objects.equals(card.getBindState(), 1)).collect(Collectors.toList());
        List<ShopBankCard> dbCardList = shopBankCardMapper.selectList(new LambdaQueryWrapper<ShopBankCard>().eq(ShopBankCard::getShopId, shopId));
        LOGGER.info("店铺：{}在数据库的银行卡列表信息查询结果：{}", shopId, dbCardList);
        if (Objects.equals(bindCardList.size(), dbCardList.size())) {
            return;
        }
        // 获取主账号卡号
        List<ShopBankCard> collect = dbCardList.stream().filter(card -> Objects.equals(card.getIsDefault(), 1)).collect(Collectors.toList());
        String cardNo = null;
        if (CollUtil.isNotEmpty(collect)) {
            cardNo = collect.get(0).getCardNo();
        }
        // 删除原有的
        shopBankCardMapper.delete(new LambdaQueryWrapper<ShopBankCard>().eq(ShopBankCard::getShopId, shopId));
        // 更新
        List<ShopBankCard> saveList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        ShopCompanyVO shopCompanyVO = shopCompanyMapper.getShopCompanyByShopIdAndStatus(shopId, AuditStatus.SUCCESSAUDIT.value());
        for (BindCard bindCard : bindCardList) {
            ShopBankCard shopBankCardDTO = new ShopBankCard();
            shopBankCardDTO.setBankName(bindCard.getBankName());
            shopBankCardDTO.setShopId(shopId);
            shopBankCardDTO.setOpeningBank(bindCard.getBankName());
            shopBankCardDTO.setUnionBank(bindCard.getUnionBank());
            shopBankCardDTO.setBankCardPro(bindCard.getBankCardPro());
            shopBankCardDTO.setBankCardNo(bindCard.getBankCardNo());
            if (Objects.equals(bindCard.getBankCardPro(), 0)) {
                shopBankCardDTO.setCardNo(bindCard.getBankCardNo());
                shopBankCardDTO.setRecipientName(shopCompanyVO.getRepresentative());
            } else if (Objects.equals(bindCard.getBankCardPro(), 1)) {
                shopBankCardDTO.setCardNo(bindCard.getAccountNo());
                shopBankCardDTO.setRecipientName(shopCompanyVO.getFirmName());
            }
            boolean isDefault = Objects.nonNull(cardNo) && (Objects.equals(cardNo, bindCard.getBankCardNo()) || Objects.equals(cardNo, bindCard.getUnionBank()));
            if (isDefault) {
                shopBankCardDTO.setIsDefault(1);
            }
            saveList.add(shopBankCardDTO);
        }
        shopBankCardMapper.insertBatch(saveList, shopId);
    }

    /**
     * 检查银行卡列表信息
     *
     * @param savedBankCardList 已保存的银行卡列表
     * @param newBankCardList   新增的银行卡列表
     * @param shopId            用于保存银行卡的店铺id
     */
    private void checkSaveBankCardList(List<ShopBankCard> savedBankCardList, List<ShopBankCard> newBankCardList, Long shopId) {
        if (savedBankCardList.size() + newBankCardList.size() > Constant.SHOP_BANK_CARD_LIMIT_NUM) {
            throw new YamiShopBindException("银行卡数量不能超过" + Constant.SHOP_BANK_CARD_LIMIT_NUM);
        }
        Map<String, Integer> bankCardMap = new HashMap<>(5);
        savedBankCardList.forEach(item -> {
            if (bankCardMap.containsKey(item.getCardNo())) {
                throw new YamiShopBindException("已添加的银行卡中存在重复账号" + item.getCardNo() + "，请先删除重复的银行卡账号");
            }
            bankCardMap.put(item.getCardNo(), 1);
        });
        newBankCardList.forEach(item -> {
            if (bankCardMap.containsKey(item.getCardNo())) {
                throw new YamiShopBindException("银行卡账号" + item.getCardNo() + "重复");
            }
            item.setIsDefault(Objects.isNull(item.getIsDefault()) ? 0 : item.getIsDefault());
            bankCardMap.put(item.getCardNo(), 1);
        });
    }

}
